home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / ALIAS.C < prev    next >
C/C++ Source or Header  |  1991-08-01  |  15KB  |  406 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    alias.c                                                         */
  3. /*                                                                    */
  4. /*    Smart routing and alias routines for pcmail.                    */
  5. /*                                                                    */
  6. /*    Copyright (C) 1989 Andrew H. Derbyshire                         */
  7. /*                                                                    */
  8. /*    Additional code                                                 */
  9. /*       Copyright (c) Richard H. Lamb 1985, 1986, 1987               */
  10. /*       Changes Copyright (c) Stuart Lynne 1987                      */
  11. /*                                                                    */
  12. /*    Updates:                                                        */
  13. /*                                                                    */
  14. /*    02 Oct 89   Alter large strings/structures to use               */
  15. /*                malloc()/free()                              ahd    */
  16. /*    08 Feb 90   Correct failure of ExtractAddress to return         */
  17. /*                non-names                                    ahd    */
  18. /*    18 Mar 90   Move checkname() and associated routines into       */
  19. /*                hostable.c                                   ahd    */
  20. /*    22 Apr 90   Modify user_at_node to correctly handle .UUCP       */
  21. /*                alias on local host.                         ahd    */
  22. /*--------------------------------------------------------------------*/
  23.  
  24. #include <ctype.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <sys/types.h>
  29.  
  30. #ifndef __TURBOC__
  31. #include <search.h>
  32. #endif
  33.  
  34. #include "lib.h"
  35. #include "hostable.h"
  36. #include "security.h"
  37. #include "usertabl.h"
  38. #include "hlib.h"
  39. #include "alias.h"
  40. #include "address.h"
  41.  
  42. static size_t AliasCount = 0;
  43.  
  44. static struct AliasTable *alias = NULL;
  45.  
  46. int nickcmp( const void *a, const void *b );
  47.  
  48. static size_t LoadAliases( void ) ;
  49.  
  50. currentfile();
  51.  
  52. /*--------------------------------------------------------------------*/
  53. /*    I n i t R o u t e r                                             */
  54. /*                                                                    */
  55. /*    Verify, initialize the global routing data                      */
  56. /*--------------------------------------------------------------------*/
  57.  
  58. boolean InitRouter()
  59. {
  60.    boolean success = TRUE;       /* Assume the input data is good       */
  61.    struct HostTable *Hptr;
  62.  
  63. /*--------------------------------------------------------------------*/
  64. /*          Verify that the user gave us a good name server           */
  65. /*--------------------------------------------------------------------*/
  66.  
  67.    Hptr = checkreal(mailserv);
  68.    if (Hptr == BADHOST)
  69.    {
  70.       printmsg(0,"mail server '%s' must be listed in SYSTEMS file",
  71.          mailserv);
  72.       success = FALSE;
  73.    }
  74.    else if (Hptr->hstatus == localhost)  /* local system?     */
  75.    {
  76.       printmsg(0,"'%s' is name of this host and cannot be mail server",
  77.             mailserv);
  78.       success = FALSE;
  79.    }
  80.  
  81. /*--------------------------------------------------------------------*/
  82. /*                          Return to caller                          */
  83. /*--------------------------------------------------------------------*/
  84.  
  85.    return success;
  86. } /* InitRouter */
  87.  
  88. /*--------------------------------------------------------------------*/
  89. /*    E x t r a c t N a m e                                           */
  90. /*                                                                    */
  91. /*    Returns full name of user, and returns address if name          */
  92. /*    is not available.                                               */
  93. /*--------------------------------------------------------------------*/
  94.  
  95. void ExtractName(char *result, char *column)
  96. {
  97.       static int recursion = 0;
  98.  
  99.       recursion++;
  100.  
  101.       printmsg((recursion > 2) ? 1:8,
  102.             "ExtractName: Getting name from '%s'",column);
  103.  
  104.       ExtractAddress(result, column, TRUE);  /* Get the full name    */
  105.       if (!strlen(result))       /* Did we get the name?             */
  106.       {                          /* No --> Get the e-mail address    */
  107.          char addr[BUFSIZ];
  108.          char path[BUFSIZ];
  109.          char node[BUFSIZ];
  110.          char *fullname;
  111.  
  112.          ExtractAddress(addr,column, FALSE);
  113.          user_at_node(addr,path,node,result);
  114.                                  /* Reduce address to basics */
  115.          fullname = AliasByAddr(node,result);
  116.          if (fullname == NULL)
  117.          {
  118.             strcat(result,"@");
  119.             strcat(result,node);
  120.          }
  121.          else
  122.             strcpy(result,fullname);
  123.       }
  124.  
  125.       printmsg((recursion > 2) ? 1: 8,"ExtractName: name is '%s'",result);
  126.  
  127.       recursion--;
  128.  
  129.       return;
  130. }  /*ExtractName*/
  131.  
  132. /*--------------------------------------------------------------------*/
  133. /*    B u i l d A d d r e s s                                         */
  134. /*                                                                    */
  135. /*    Builds a standard address format, with aliasing as              */
  136. /*    required.                                                       */
  137. /*--------------------------------------------------------------------*/
  138.  
  139. void BuildAddress(char *result, const char *input)
  140. {
  141.    char addr[MAXADDR];
  142.    char name[MAXADDR];
  143.    char user[BUFSIZ];
  144.    char path[BUFSIZ];
  145.    char node[BUFSIZ];
  146.    char *fulladdr;
  147.  
  148. /*--------------------------------------------------------------------*/
  149. /*   It must be a real address, possibly with a name attached; get    */
  150. /*   the address portion, break the address into user and node, and   */
  151. /*   then see if we know the person by address                        */
  152. /*--------------------------------------------------------------------*/
  153.  
  154.       ExtractAddress(addr,input,FALSE);   /* Get user e-mail addr    */
  155.       user_at_node(addr,path,node,user);  /* Break address down      */
  156.  
  157.       fulladdr = AliasByAddr(node,user);  /* Alias for the address?  */
  158.       if (fulladdr != NULL)            /* Yes --> Use it             */
  159.       {
  160.          strcpy(result,fulladdr);
  161.          return;
  162.       } /* if */
  163.  
  164. /*--------------------------------------------------------------------*/
  165. /*   We don't know the address yet; get the name the user provided,   */
  166. /*   and then normalize the address                                   */
  167. /*--------------------------------------------------------------------*/
  168.  
  169.       ExtractAddress(name,input,TRUE);    /* Also get their name     */
  170.  
  171.       if (strlen(name))             /* Did we find a name for user?  */
  172.       {                             /* Yes --> Return it             */
  173.          char *s = strchr(node, '.');
  174.          if ((s == NULL) || equalni( s, ".UUCP", 5))
  175.                                     /* Simple name or UUCP domain?   */
  176.          {                          /* Yes--> Use original address   */
  177.             size_t pathlen = strlen(path);/* Save len of orig path   */
  178.             if ((pathlen > strlen(addr)) &&
  179.                 (!equal(node,path)) && /* Target not a known host?   */
  180.                 equaln(addr,path, strlen(path)) && /* & host starts  */
  181.                 (addr[pathlen] == '!'))   /* ...the address?         */
  182.                fulladdr = &addr[pathlen + 1];   /* Yes --> Drop it   */
  183.             else
  184.                fulladdr = addr;  /* No --> Use full address          */
  185.             sprintf(result,"(%s) %s", name, addr);
  186.          } /* (strchr(node, '.') == NULL) */
  187.          else                    /* No --> Use RFC-822 format        */
  188.             sprintf(result,"\"%s\" <%s@%s>", name, user, node);
  189.       } /* if strlen(name) */
  190.       else
  191.          strcpy(result,addr);    /* No name, just use the original   */
  192. } /* BuildAddress */
  193.  
  194.  
  195. /*--------------------------------------------------------------------*/
  196. /*    A l i a s B y N i c k                                           */
  197. /*                                                                    */
  198. /*    Locate a mail address by search the alias table.  Returns TRUE  */
  199. /*    if alias found and has address, otherwise FALSE.                */
  200. /*--------------------------------------------------------------------*/
  201.  
  202. char *AliasByNick(const char *nick)
  203. {
  204.    int   upper;
  205.    int   lower;
  206.  
  207.    if (!AliasCount)
  208.       AliasCount = LoadAliases();
  209.  
  210.    upper = AliasCount - 1;
  211.    lower = 0;
  212.  
  213.    while (upper >= lower)
  214.    {
  215.       int midpoint;
  216.       int hit;
  217.  
  218.       midpoint = ( upper + lower ) / 2;
  219.       hit = stricmp(nick,alias[midpoint].anick);
  220.       if (!hit)
  221.          return alias[midpoint].afull;
  222.       if ( hit > 0 )
  223.          lower = midpoint + 1;
  224.       else
  225.          upper = midpoint - 1;
  226.    }
  227.    return NULL;
  228. }
  229.  
  230.  
  231. /*--------------------------------------------------------------------*/
  232. /*    A l i a s B y A d d r                                           */
  233. /*                                                                    */
  234. /*    Locate a mail address by search the alias table.  Returns TRUE  */
  235. /*    if alias found and has address, otherwise FALSE                 */
  236. /*--------------------------------------------------------------------*/
  237.  
  238. char *AliasByAddr(const char *node, const char *user)
  239. {
  240.    size_t current = 0;
  241.  
  242.    if (!AliasCount)
  243.       AliasCount = LoadAliases();
  244.  
  245.    while (current < AliasCount)
  246.    {
  247.       int hit;
  248.  
  249.       hit = stricmp(node,alias[current].anode);
  250.       if (!hit)
  251.       {
  252.          hit = stricmp(user,alias[current].auser);
  253.          if (!hit)
  254.             return alias[current].afull;
  255.       }
  256.       current++;
  257.    }
  258.    return NULL;
  259.  
  260. }
  261.  
  262.  
  263. /*--------------------------------------------------------------------*/
  264. /*    L o a d A l i a s e s                                           */
  265. /*                                                                    */
  266. /*    Initializes the address alias table; returns number of aliases  */
  267. /*    loaded                                                          */
  268. /*--------------------------------------------------------------------*/
  269.  
  270. size_t LoadAliases(void)
  271. {
  272.    FILE *ff;
  273.    char buf[BUFSIZ];
  274.    char *token;
  275.    size_t   elements = 0;
  276.    size_t   max_elements = UserElements + 20;
  277.    size_t   subscript;
  278.    struct AliasTable *hit;           /* temporary pointer for searching  */
  279.    struct AliasTable target;
  280.  
  281.  
  282.    checkuser( mailbox );   /* Force the table to be loaded           */
  283.    alias = calloc(max_elements, sizeof(*alias));
  284.    checkref(alias);
  285.  
  286. /*--------------------------------------------------------------------*/
  287. /*                   Actually load the alias table                    */
  288. /*--------------------------------------------------------------------*/
  289.  
  290.    if (aliases != NULL )      /* Did the user specify aliases file?  */
  291.    {
  292.  
  293.       ff = FOPEN(aliases, "r", TEXT);
  294.       if (ff == NULL)
  295.       {
  296.          printerr(aliases);
  297.          return elements;
  298.       } /* if */
  299.  
  300.       while (! feof(ff))
  301.       {
  302.          if (fgets(buf,BUFSIZ,ff) == NULL)   /* Try to read a line      */
  303.             break;                  /* Exit if end of file              */
  304.          token = strtok(buf," \t\n");
  305.          if (token == NULL)         /* Any data?                        */
  306.             continue;               /* No --> read another line         */
  307.          if (token[0] == '#')
  308.             continue;                  /* Line is a comment; loop again */
  309.  
  310.          /* Add the alias to the table.  Note that we must add the nick */
  311.          /* to the table ourselves (rather than use lsearch) because    */
  312.          /* we must make a copy of the string; the *token we use for    */
  313.          /* the search is in the middle of our I/O buffer!              */
  314.          /*
  315.          /* I was burned, _you_ have been warned.                       */
  316.  
  317.          target.anick = token;
  318.  
  319.          hit = (void *) lfind(&target, alias, &elements , sizeof(alias[0]),
  320.              nickcmp);
  321.          if (hit == NULL)
  322.          {
  323.             char node[MAXADDR];
  324.             char user[MAXADDR];
  325.             char path[MAXADDR];
  326.             char addr[MAXADDR];
  327.             char *eos;
  328.  
  329.             if (elements == max_elements)
  330.             {
  331.                 max_elements = max_elements * 2;
  332.                 alias = realloc(alias, max_elements * sizeof(*alias));
  333.                 checkref(alias);
  334.             }
  335.  
  336.             alias[elements].anick = strdup(token);
  337.             token = strtok(NULL,"");    /* Get rest of string         */
  338.  
  339.             while ( strlen(token) && isspace(*token))
  340.                token++;
  341.             eos = token + strlen(token) - 1;
  342.             while ( strlen(token) && isspace(*eos))
  343.             {
  344.                *eos = '\0';
  345.                eos--;
  346.             }
  347.  
  348.             alias[elements].afull = strdup(token);
  349.             ExtractAddress(addr,alias[elements].afull,FALSE);
  350.             user_at_node(addr,path,node,user);
  351.             alias[elements].anode = strdup(node);
  352.             alias[elements].auser = strdup(user);
  353.             elements += 1;
  354.          }
  355.          else
  356.             printmsg(0,"LoadAliases: Duplicate alias '%s' in table",token);
  357.       }
  358.       fclose(ff);
  359.    } /* if (aliases != NULL ) */
  360.  
  361. /*--------------------------------------------------------------------*/
  362. /*           Add the local users as final aliases in table            */
  363. /*--------------------------------------------------------------------*/
  364.  
  365.    alias = realloc(alias, (elements + UserElements) * sizeof(*alias));
  366.                               /* Resize table to final known size    */
  367.    checkref(alias);
  368.  
  369.    for ( subscript = 0; subscript < UserElements; subscript++, elements++)
  370.    {
  371.       alias[elements].anick = "";   /* No nickname, only good for addr  */
  372.       if (bflag[F_BANG])
  373.          sprintf(buf, "(%s) %s!%s",
  374.                users[subscript].realname, domain,
  375.                users[subscript].uid);
  376.       else
  377.          sprintf(buf, "\"%s\" <%s@%s>", users[subscript].realname,
  378.                users[subscript].uid, domain );
  379.       alias[elements].afull = strdup(buf);
  380.       alias[elements].anode = nodename;
  381.       alias[elements].auser = users[subscript].uid;
  382.    } /* for */
  383.  
  384. /*--------------------------------------------------------------------*/
  385. /*                         Now sort the table                         */
  386. /*--------------------------------------------------------------------*/
  387.  
  388.    qsort(alias, elements ,sizeof(alias[0]) , nickcmp);
  389.  
  390.    return (elements) ;
  391. } /*LoadAliases*/
  392.  
  393.  
  394. /*--------------------------------------------------------------------*/
  395. /*   n i c k c m p                                                    */
  396. /*                                                                    */
  397. /*   Accepts indirect pointers to two strings and compares them using */
  398. /*   stricmp (case insensitive string compare)                        */
  399. /*--------------------------------------------------------------------*/
  400.  
  401. int nickcmp( const void *a, const void *b )
  402. {
  403.    return stricmp(((struct AliasTable *)a)->anick,
  404.          ((struct AliasTable *)b)->anick);
  405. }  /*nickcmp*/
  406.